﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace wontec_claw
{
    class pipeline
    {
        char startchar = '>';
        char endchar = '\n';

        int waitLen = 4;
        bool waitFlag = false;
        int waitTime = 500;
        int resendtime = 0;
        int resendcount = 3;

        int sendtick = 150;

        List<byte> rxbuffer;
        bool exit = false;
        StringBuilder datainfocache;

        Action<string> sendDataAction;

        List<string> sendbuff = new List<string>();
        List<string> waitBuff = new List<string>();
        List<int> waitCount = new List<int>();

        List<string> SendReady = new List<string>();
        Dictionary<string, int> SendMap = new Dictionary<string, int>();
        Dictionary<string, string> waitData = new Dictionary<string, string>();
        Dictionary<string, string> waitData2 = new Dictionary<string, string>();

        public bool Enable { get; set; }

        public void SendData(string str,string waitstr = "")
        {
            if (waitstr.Length != 0)
                SendDataPipe(str, waitstr);
            else
                sendDataAction(str);
        }

        public void SendDataPipe(string str,string waitstr)
        {
            if (SendMap.ContainsKey(str))
                SendMap[str] = 65536 * resendcount;
            else
                SendMap.Add(str, 65536 * resendcount);



            if (waitData.ContainsKey(waitstr))
                waitData[waitstr] = str;
            else
                waitData.Add(waitstr, str);


            if (waitData2.ContainsKey(str))
                waitData2[str] = waitstr;
            else
                waitData2.Add(str, waitstr);
        }

        public pipeline(List<byte> rx,Action<string> output,Action<string> send)
        {
            sendDataAction = send;
            datainfocache = new StringBuilder();
            rxbuffer = rx;
            //new Thread(() => {
            //    while (!exit)
            //    {
                    
            //    }
            //}).Start();

            new Thread(() => {
                int lastCount=0;
                int lastPos=0;
                byte[] datainfobigchar = new byte[2];
                while (!exit)
                {
                    if (!Enable) goto L1;
                    try
                    {
                        if (SendMap.Count > 0)
                            foreach (var k in SendMap.Keys.ToArray())
                            {
                                int value = SendMap[k];
                                if ((value & 0xffff) < 10)
                                {
                                    if (value > 0xffff)
                                    {
                                        value -= 0xffff - waitTime;
                                        SendMap[k] = value;
                                        SendReady.Add(k);
                                    }
                                    else
                                    {
                                        var kx = waitData2[k];
                                        SendMap.Remove(k);
                                        waitData2.Remove(k);
                                        waitData.Remove(kx);
                                        value = 0;
                                    }
                                }
                                else
                                {
                                    value -= 10;
                                    SendMap[k] = value;
                                }
                                if (resendtime > 0)
                                    resendtime -= 10;
                                else if (SendReady.Count > 0)
                                    {
                                        resendtime = sendtick;
                                        sendDataAction(SendReady[0]);
                                        SendReady.RemoveAt(0);
                                    }
                            }
                    }
                    catch { }

                    try
                    {
                        if (lastCount != rxbuffer.Count)
                        {
                            if (rxbuffer.Count == 0) return;
                            while (rxbuffer.Count != 0)
                            {
                                if (rxbuffer[0] != startchar)
                                {
                                    if (rxbuffer[0] > 126)
                                    {
                                        if (datainfobigchar[0] == 0)
                                            datainfobigchar[0] = rxbuffer[0];
                                        else
                                        {
                                            datainfobigchar[1] = rxbuffer[0];
                                            datainfocache.Append(Encoding.Default.GetString(datainfobigchar));
                                            datainfobigchar[0] = 0;
                                        }
                                    }
                                    else
                                    {
                                        if (datainfobigchar[0] != 0)
                                        {
                                            datainfocache.Append((char)datainfobigchar[0]);
                                            datainfobigchar[0] = 0;
                                        }
                                        datainfocache.Append((char)rxbuffer[0]);
                                    }
                                    rxbuffer.RemoveAt(0);
                                    continue;
                                }
                                break;
                            }
                            lastCount = rxbuffer.Count;
                            int i;
                            for (i = lastPos; i < lastCount; i++)
                            {
                                if (rxbuffer[i] == endchar)
                                {
                                    byte[] b = new byte[i + 1];
                                    for (int j = 0; j < i + 1; j++)
                                    {
                                        b[j] = rxbuffer[0];
                                        rxbuffer.RemoveAt(0);
                                    }
                                    lastCount = 0;
                                    lastPos = 0;
                                    string recvcmd = Encoding.Default.GetString(b, 0, b.Length);
                                    var key = recvcmd.Substring(0, waitLen);
                                    if (waitData.ContainsKey(key))
                                    {
                                        SendMap.Remove(waitData[key]);
                                        waitData2.Remove(waitData[key]);
                                        waitData.Remove(key);
                                    }
                                    output(recvcmd);
                                    goto L1;
                                    //return;
                                }
                            }
                            lastPos = i;
                        }
                    }
                    catch { }
                    L1:
                    Thread.Sleep(1);
                }
            }).Start();
        }
    }
}
